#include "StdAfx.h"
#include "cEditor.h"



cEditor editor;
Color background;

void sLine::updateContent(EE::Str con) {
	content = con;
	background = WHITE;

	// check for consitency
	// do not calculate if the last character is an operator
	if ((content[content.length() - 1] == '*')
		||(content[content.length() - 1] == '+')
		||(content[content.length() - 1] == '-')) {
			return;
	}
	// check for bracket consistency
	Int brackets = 0;
	for (Int pos = 0; pos < content.length(); pos++) {
		if ((content[pos] == '(')||(content[pos] == '{')) {
			brackets++;
			if (brackets > 1) {
				// this means brackets are nested
				background = RED;
				return;
			}
		}
		if ((content[pos] == ')')||(content[pos] == '}')) {
			brackets--;
			if (brackets < 0) {
				// this means more brackets are closed than there were open
				background = RED;
				return;
			}
		}
	}

	// if there is still an open bracket, probably the user is typing some right now
	// do not renew blocks, but also don't change background to warning
	if (brackets) {
		return;
	}


	blocks.clear();
	// make vector
	std::vector<Int> components;
	std::vector<Color> colors;
	std::vector<Str> captions;
	Str number;
	Str tempCaption;
	Str tempColor;
	Bool inputColor = false;
	Bool inputCaption = false;

	for (Int pos = 0; pos < content.length(); pos++) {

		// close braces and brackets
		if (content[pos] == ')') {
			inputColor = false;
		}
		if (content[pos] == '}') {
			inputCaption = false;
		}

		// add to color or caption if inside brackets
		if (inputColor) tempColor += content[pos];
		if (inputCaption) tempCaption += content[pos];

		// add digits to number
		if ((content[pos] >= '0')&&(content[pos] <= '9')&&(!inputColor)&&(!inputCaption)) {
			number += content[pos];
		} else {
			// if a number exists add it as an int
			if (number.length()) {
				components.push_back(TextInt(number));
				number.clear();
			}
			// check for operators
			if (!inputColor && !inputCaption) {
				if (content[pos] == '*') components.push_back(-1);
				if (content[pos] == '+') components.push_back(-2);
				if (content[pos] == '-') components.push_back(-3);
				if (content[pos] == 'r') components.push_back(-4);
				if (content[pos] == '.') components.push_back(-5);
			}

			// look for color code
			if (content[pos] == '(') {
				inputColor = true;
			}
			if (content[pos] == ')') {
				inputColor = false;
				if (Equal(tempColor, "grey")) {
					colors.push_back(GREY_LIGHT);
					components.push_back(-6);
				} else if (Equal(tempColor, "red")) {
					colors.push_back(RED_LIGHT);
					components.push_back(-6);
				} else if (Equal(tempColor, "green")) {
					colors.push_back(GREEN_LIGHT);
					components.push_back(-6);
				} else if (Equal(tempColor, "blue")) {
					colors.push_back(BLUE_LIGHT);
					components.push_back(-6);
				} else if (Equal(tempColor, "yellow")) {
					colors.push_back(YELLOW_LIGHT);
					components.push_back(-6);
				} else if (Equal(tempColor, "cyan")) {
					colors.push_back(CYAN_LIGHT);
					components.push_back(-6);
				} else if (Equal(tempColor, "purple")) {
					colors.push_back(PURPLE_LIGHT);
					components.push_back(-6);
				} else if (Equal(tempColor, "orange")) {
					colors.push_back(ORANGE_LIGHT);
					components.push_back(-6);
				} else if (Equal(tempColor, "turqoise")) {
					colors.push_back(TURQ_LIGHT);
					components.push_back(-6);
				} else {
					background = RED;
				}
				tempColor.clear();
			}

			// look for caption code
			if (content[pos] == '{') {
				inputCaption = true;
			}
			if (content[pos] == '}') {
				inputCaption = false;
				captions.push_back(tempCaption);
				components.push_back(-7);
				tempCaption.clear();
			}
		}
	}

	// add last number
	if (number.length()) {
		components.push_back(TextInt(number));
	}

	// do multiplications
	Int size = components.size();
	for (Int pos = 0; pos < size; pos++) {
		if (components[pos] == -1) {
			components[pos-1] *= components[pos+1];
			components.erase(components.begin()+pos);
			components.erase(components.begin()+pos);
			size -= 2;
		}
	}

	// do +/-
	for (Int pos = 0; pos < size; pos++) {
		if (components[pos] == -2) {
			components[pos-1] += components[pos+1];
			components.erase(components.begin()+pos);
			components.erase(components.begin()+pos);
			size -= 2;
		} else if (components[pos] == -3) {
			components[pos-1] -= components[pos+1];
			components.erase(components.begin()+pos);
			components.erase(components.begin()+pos);
			size -= 2;
		}
	}

	// construct blocks
	Bool space = false;
	Bool addColor = false;
	Bool addCaption = false;
	Int captionPos = 0;
	Int colorPos  = 0;

	Int ruler = 0;
	for (Int pos = 0; pos < components.size(); pos++) {
		if (components[pos] > 0) {
			if (!space) {
				// add block
				sBlock temp;
				temp.begin = ruler;
				temp.end = components[pos];
				// check for caption
				if (addCaption) {
					temp.caption = captions.at(captionPos);
					addCaption = false;
					captionPos++;
				}
				// check for color
				if (addColor) {
					temp.color = colors.at(colorPos);
					addColor = false;
					colorPos++;
				} else {
					temp.color = BLACK;
				}
				// update ruler position for next block
				ruler += components[pos];
				// save block
				blocks.push_back(temp);
			} else {
				space = false;
				ruler += components[pos];
			}
		} else if (components[pos] == -4) {
			space = true;
		} else if (components[pos] == -6) {
			addColor = true;
		} else if (components[pos] == -7) {
			addCaption = true;
		}
	}
}



void cEditor::create() {
	if (obj.load("Gui/editor.gobj")) {
		globalEditor = &obj.getWindow("globalEditor");
		measureEditor = &obj.getWindow("measureEditor");
		measureEditor->hide();

		divisionText = &obj.getTextLine("divisionText");
		divisionText->func(divisionTextChanged);
		divisionText->set("100");
		divisionSteps = &obj.getTextLine("divisionSteps");
		divisionSteps->func(divisionStepsChanged);
		divisionSteps->set("50");
		bpmText = &obj.getTextLine("bpmText");
		bpmText->func(bpmTextChanged);
		bpmText->set("2");
		advancedButton = &obj.getButton("advancedButton");
		advancedButton->func(advancedButtonClicked);
		captionText = &obj.getTextLine("captionText");
		captionText->func(captionTextChanged);
		offsetText = &obj.getTextLine("offsetText");
		offsetText->func(offsetTextChanged);

		//advanced measure structures
		structText = &obj.getTextLine("structText");
		structText->func(structTextChanged);
		structCancel = &obj.getButton("structCancel");
		structCancel->func(structCancelClicked);
		structOk = &obj.getButton("structOk");
		structOk->func(structOkClicked);

		newButton = &obj.getButton("newButton");
		newButton->func(newButtonClicked);
		loadButton = &obj.getButton("loadButton");
		loadButton->func(loadButtonClicked);
		saveButton = &obj.getButton("saveButton");
		saveButton->func(saveButtonClicked);
		makeScreenshot = false;

		//line checkboxes
		ch[0] = &obj.getCheckBox("linecheck1");
		ch[0]->func(ch1Clicked);
		ch[1] = &obj.getCheckBox("linecheck2");
		ch[1]->func(ch2Clicked);
		ch[2] = &obj.getCheckBox("linecheck3");
		ch[2]->func(ch3Clicked);
		ch[3] = &obj.getCheckBox("linecheck4");
		ch[3]->func(ch4Clicked);
		ch[4] = &obj.getCheckBox("linecheck5");
		ch[4]->func(ch5Clicked);
		ch[5] = &obj.getCheckBox("linecheck6");
		ch[5]->func(ch6Clicked);
		ch[6] = &obj.getCheckBox("linecheck7");
		ch[6]->func(ch7Clicked);
		ch[7] = &obj.getCheckBox("linecheck8");
		ch[7]->func(ch8Clicked);
		ch[8] = &obj.getCheckBox("linecheck9");
		ch[8]->func(ch9Clicked);
		ch[9] = &obj.getCheckBox("linecheck10");
		ch[9]->func(ch10Clicked);
		ch[0]->set(true);

		resetLines();

		// color
		globalColorButton = &obj.getButton("globalColorButton");
		globalColorButton->func(globalColorButtonClicked);
		Gui += colorPicker.create("");
		colorPicker.hide();
		colorPicker.level(1);
		colorToGlobal = false;

		//editRegion = &obj.getRegion("editRegion");
		//blockList.create(editRegion);
		lineText = &obj.getTextLine("lineText");
		lineText->func(lineTextChanged);

		Gui += obj;

		Gui += fileWindow.create("data", CNULL, "Data", loadData, saveData);
		fileWindow.path_mode = WIN_IO_PM_PART;
		fileWindow.ext("scheme");
	}

	advancedBpm = false;
}

void cEditor::bpmTextChanged(Ptr) {
	Str tmp = (*editor.bpmText)();
	Int bpm = TextInt(tmp);
	if (bpm > 0) {
		background = WHITE;
		editor.bpm = bpm;
	} else {
		background = RED;
	}
}
	 
void cEditor::divisionStepsChanged(Ptr) {
	Str tmp = (*editor.divisionSteps)();
	editor.steps = TextInt(tmp);
	if (editor.steps > 0) {
		background = WHITE;
	} else {
		background = RED;
	}
}

void cEditor::divisionTextChanged(Ptr) {
	Str tmp = (*editor.divisionText)();
	editor.division = TextInt(tmp);
	if (editor.division > 0) {
		background = WHITE;
	} else {
		background = RED;
	}
}

void cEditor::advancedButtonClicked(Ptr) {
	editor.measureEditor->show();
	editor.advancedBpm = true;
}

void cEditor::captionTextChanged(Ptr) {
	editor.lines[editor.activeLine].caption = (*editor.captionText)();
}

void cEditor::structCancelClicked(Ptr) {
	editor.measureEditor->hide();
	editor.advancedBpm = false;
	editor.bpmText->back_color = WHITE;
	editor.bpmText->disabled(false);
}

void cEditor::structOkClicked(Ptr) {
	editor.measureEditor->hide();
	editor.advancedBpm = true;
	editor.bpmText->back_color = GREY_LIGHT;
	editor.bpmText->disabled(true);
}

void cEditor::structTextChanged(Ptr) {
	Str tmp = (*editor.structText)();
	editor.bpmLogic.clear();
	Str number;

	for (Int i = 0; i < tmp.length(); i++) {
		if (tmp[i] == '.') {
			Int x = TextInt(number);
			if (x) {
				editor.bpmLogic.push_back(x);
				number.clear();
			}
		} else {
			number += tmp[i];
		}
	}
	
	Int x = TextInt(number);
	if (x) {
		editor.bpmLogic.push_back(x);
		number.clear();
	}
	if (editor.bpmLogic.size()) {
		background = WHITE;
	} else {
		background = RED;
	}
}

void cEditor::chToggle(Int nr) {
	for (Int x = 0; x < 10; x++) {
		if (nr == x) {
			editor.ch[x]->set(true, true);
			editor.setActiveLine(x);
		} else {
			editor.ch[x]->set(false, true);
		}
	}
}

void cEditor::setActiveLine(Int line) {
	activeLine = line;
	captionText->set(lines[activeLine].caption);
	globalColorButton->color = lines[activeLine].color;
	lineText->set(lines[activeLine].content);
}

void cEditor::ch1Clicked(Ptr) { editor.chToggle(0); }
void cEditor::ch2Clicked(Ptr) { editor.chToggle(1); }
void cEditor::ch3Clicked(Ptr) { editor.chToggle(2); }
void cEditor::ch4Clicked(Ptr) { editor.chToggle(3); }
void cEditor::ch5Clicked(Ptr) { editor.chToggle(4); }
void cEditor::ch6Clicked(Ptr) { editor.chToggle(5); }
void cEditor::ch7Clicked(Ptr) { editor.chToggle(6); }
void cEditor::ch8Clicked(Ptr) { editor.chToggle(7); }
void cEditor::ch9Clicked(Ptr) { editor.chToggle(8); }
void cEditor::ch10Clicked(Ptr) { editor.chToggle(9); }

void cEditor::resetLines() {
	lines.clear();
	for (Int x = 0; x < 10; x++) {
		sLine temp;
		temp.color = Color(255, 125, 125);
		lines.push_back(temp);
	}
}

void cEditor::globalColorButtonClicked(Ptr) {
	editor.colorPicker.show();
	editor.colorPicker.set(editor.lines[editor.activeLine].color.asVec4());
	editor.colorToGlobal = true;
}

void cEditor::lineTextChanged(Ptr) {
	editor.lines[editor.activeLine].updateContent((*editor.lineText)());

}

void cEditor::offsetTextChanged(Ptr) {
	editor.offset = TextInt((*editor.offsetText)());
}

void cEditor::newButtonClicked(Ptr) {
	editor.resetValues();
}

void cEditor::saveButtonClicked(Ptr) {
	editor.fileWindow.save();
}

void cEditor::loadButtonClicked(Ptr) {
	editor.fileWindow.load();
}

void cEditor::loadData(CChar *name, Ptr user) {
	editor.resetValues();

	FileText f;

	if (f.read(name)) {
		Int x = 0;
		f.depth = 1;
		for (;f.level();) {
			if (f.cur("Division")) editor.division = f.getInt(); 
			else if (f.cur("Steps")) editor.steps = f.getInt();
			else if (f.cur("beatsPerMeasure")) editor.bpm = f.getInt();
			else if (f.cur("AdvancedBpm")) editor.advancedBpm = f.getBool();
			else if (f.cur("Bpmstructure")) editor.structText->set(f.getName());
			else if (f.cur("Offset")) editor.offset = f.getInt();
			else if (f.cur("Caption0")) editor.lines[0].caption = f.getName();
			else if (f.cur("Color0")) editor.lines[0].color = Color(f.getVec4());
			else if (f.cur("Content0")) editor.lines[0].content = f.getName();
			else if (f.cur("Caption1")) editor.lines[1].caption = f.getName();
			else if (f.cur("Color1")) editor.lines[1].color = Color(f.getVec4());
			else if (f.cur("Content1")) editor.lines[1].content = f.getName();
			else if (f.cur("Caption2")) editor.lines[2].caption = f.getName();
			else if (f.cur("Color2")) editor.lines[2].color = Color(f.getVec4());
			else if (f.cur("Content2")) editor.lines[2].content = f.getName();
			else if (f.cur("Caption3")) editor.lines[3].caption = f.getName();
			else if (f.cur("Color3")) editor.lines[3].color = Color(f.getVec4());
			else if (f.cur("Content3")) editor.lines[3].content = f.getName();
			else if (f.cur("Caption4")) editor.lines[4].caption = f.getName();
			else if (f.cur("Color4")) editor.lines[4].color = Color(f.getVec4());
			else if (f.cur("Content4")) editor.lines[4].content = f.getName();
			else if (f.cur("Caption5")) editor.lines[5].caption = f.getName();
			else if (f.cur("Color5")) editor.lines[5].color = Color(f.getVec4());
			else if (f.cur("Content5")) editor.lines[5].content = f.getName();
			else if (f.cur("Caption6")) editor.lines[6].caption = f.getName();
			else if (f.cur("Color6")) editor.lines[6].color = Color(f.getVec4());
			else if (f.cur("Content6")) editor.lines[6].content = f.getName();
			else if (f.cur("Caption7")) editor.lines[7].caption = f.getName();
			else if (f.cur("Color7")) editor.lines[7].color = Color(f.getVec4());
			else if (f.cur("Content7")) editor.lines[7].content = f.getName();
			else if (f.cur("Caption8")) editor.lines[8].caption = f.getName();
			else if (f.cur("Color8")) editor.lines[8].color = Color(f.getVec4());
			else if (f.cur("Content8")) editor.lines[8].content = f.getName();
			else if (f.cur("Caption9")) editor.lines[9].caption = f.getName();
			else if (f.cur("Color9")) editor.lines[9].color = Color(f.getVec4());
			else if (f.cur("Content9")) editor.lines[9].content = f.getName();

		}
	}

	editor.updateGuiValues();
}

void cEditor::saveData(CChar *name, Ptr user) {
	FileText f;

	if(f.write(name)) {
		f.put("Division = ", editor.division);
		f.put("Steps = ", editor.steps);
		f.put("beatsPerMeasure = ", editor.bpm);
		f.putName("Bpmstructure = ", (*editor.structText)());
		f.put("AdvancedBpm = ", editor.advancedBpm);
		f.put("Offset = ", editor.offset);
		for (Int x = 0; x < 10; x++) {
			Str tmp = "Caption"; tmp += x; tmp += " = ";
			f.putName(tmp, editor.lines[x].caption);
			tmp = "Color"; tmp += x; tmp += " = ";
			f.put(tmp, editor.lines[x].color.asVec4());
			tmp = "Content"; tmp += x; tmp += " = ";
			f.putName(tmp, editor.lines[x].content);
		}
	}

	editor.makeScreenshot = true;
	editor.imageName = name;
	// remove .scheme
	editor.imageName.remove(editor.imageName.length()-7, 7);
	editor.imageName += ".png";
}

void cEditor::resetValues() {
	division = 100;
	steps = 50;
	bpm = 2;
	structText->set("");
	editor.measureEditor->hide();
	editor.advancedBpm = false;
	editor.bpmText->back_color = WHITE;
	editor.bpmText->disabled(false);
	offset = 0;
	resetLines();
	chToggle(0);

}

void cEditor::updateGuiValues() {
	divisionText->set(TextInt(division), true);
	divisionSteps->set(TextInt(steps), true);
	bpmText->set(TextInt(bpm), true);
	if (advancedBpm) {
		bpmText->back_color = GREY_LIGHT;
		bpmText->disabled(true);
	} else {
		bpmText->back_color = WHITE;
		bpmText->disabled(false);
	}
	chToggle(0);
	for (Int x = 0; x < 10; x++) {
		lines[x].updateContent(lines[x].content);
	}
}